package negocio;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import beans.MesaVO;
import beans.SectorVO;

import exceptions.MesaException;

@Entity
@Table(name="sectores")
public class Sector implements Serializable 
{
	private static final long serialVersionUID = 1L;
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column(name="id_sector", nullable=false)
	private int id_sector;
	
	
	@Column(name="nombre", nullable=true)
	private String nombre;
	
	@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
	@JoinColumn(name="id_sector", referencedColumnName="id_sector")
	private List<Mesa> mesas = new ArrayList<>();
	
	public int getId_sector() {
		return id_sector;
	}
	public void setId_sector(int id_sector) {
		this.id_sector = id_sector;
	}
	public String getNombre() {
		return nombre;
	}
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
	public List<Mesa> getMesas() {
		return mesas;
	}
	public void setMesas(List<Mesa> mesas) {
		this.mesas = mesas;
	}
	
	public SectorVO getVO()
	{
		SectorVO sectVO = new SectorVO();
		sectVO.setId_sector(getId_sector());
		ArrayList<MesaVO> mesasVO = new ArrayList<MesaVO>();
		for (int i = 0 ; i < getMesas().size() ; i++)
		{
			MesaVO mesaVO = getMesas().get(i).getVO();
			mesasVO.add(mesaVO);
		}
		sectVO.setMesas(mesasVO);
		sectVO.setNombre(getNombre());
		
		return sectVO;
	}
	
	
	// toString
	
	
	@Override
	public String toString() {
		return "Sector [id_sector=" + id_sector + ", nombre=" + nombre
				+ ", mesas=" + mesas + "]";
	}
	
	
	// hashcode and equals
	
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id_sector;
		result = prime * result + ((mesas == null) ? 0 : mesas.hashCode());
		result = prime * result + ((nombre == null) ? 0 : nombre.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Sector other = (Sector) obj;
		if (id_sector != other.id_sector)
			return false;
		if (mesas == null) {
			if (other.mesas != null)
				return false;
		} else if (!mesas.equals(other.mesas))
			return false;
		if (nombre == null) {
			if (other.nombre != null)
				return false;
		} else if (!nombre.equals(other.nombre))
			return false;
		return true;
	}
	
	public void abrirMesa(int numeroMesa, int cantPersonas, 
			Date fechaApertura) 
			throws MesaException 
	{
		Mesa m = buscarMesa(numeroMesa);
		m.abrirMesa(cantPersonas, fechaApertura);
	}
	
	public void unirMesas(List<Integer> nroMesas, int maxCantPersonas) 
			throws MesaException
	{
		ArrayList<Mesa> mesasAUnir = new ArrayList<Mesa>();
		for(int nroMesa : nroMesas){
			Mesa m = this.buscarMesa(nroMesa);
			m.setEstado("Combinada");
			mesasAUnir.add(m);
		}
		
		int numeroMesa = this.calcularNumeroMesaDisponible();
		Mesa m = new MesaCombinada(numeroMesa, mesasAUnir, maxCantPersonas);
		mesas.add(m);
	}
	
	public void cerrarMesa(int numeroMesa) throws MesaException
	{
		Mesa m = this.buscarMesa(numeroMesa);
		m.cerrarMesa();
	}
	
	public void liberarMesa(int numeroMesa) throws MesaException
	{
		Mesa m = this.buscarMesa(numeroMesa);
		m.liberarMesa();
		if(m instanceof MesaCombinada){
			mesas.remove(m);
		}
	}
	
	public Mesa buscarMesa(int numeroMesa) throws MesaException
	{
		for(Mesa m : mesas){
			if(m.getNumeroMesa() == numeroMesa)
				return m;
		}
		throw new MesaException("Mesa no encontrada.");
	}
	
	private int calcularNumeroMesaDisponible()
	{
		int numeroMesaMasAlto = 0;
		for(Mesa m : mesas){
			if(m.getNumeroMesa() > numeroMesaMasAlto)
				numeroMesaMasAlto = m.getNumeroMesa();
		}
		return numeroMesaMasAlto + 1;
	}
	public void buildFromVO(SectorVO sectorVO) 
	{
		this.nombre = sectorVO.getNombre();
		ArrayList<MesaVO> mesasVO = sectorVO.getMesas();
		for(MesaVO mesaVO : mesasVO){
			Mesa mesa = new Mesa();
			mesa.buildFromVO(mesaVO);
			this.mesas.add(mesa);
		}
	}
}
